ffmpeg 添加视频加文字水印 您所在的位置:网站首页 ffmpeg 特效滤镜 ffmpeg 添加视频加文字水印

ffmpeg 添加视频加文字水印

2023-12-18 17:17| 来源: 网络整理| 查看: 265

使用ffmpeg 命令行给视频添加文字水印,利用drawtext滤镜,如果是代码上api调用,也是一样的用法,创建好滤镜图, 在滤镜图描述字符串中,把这里命令行的参数拷贝过去替换就行,改动非常方便。 给视频添加文字,简单地添加一个helloworld 很方便,在《FFMPEG 从入门到精通》-刘歧 书第6.2章 有讲解,不过讲的非常浅显,不解其中参数的意义,总是期望哪里有一份官方说明使用手册来告诉我们这些参数的意义,遗憾并没有找到,这本书虽然是ffmpeg官网推荐的却也非常浅显,基本没有涉及源码,索性从源码里去寻找答案,这才是最完整的第一手资料。这里结合源代码,来分析分析这个滤镜用法。 源码vf_drawtext.c 添加文字我们关心的几个问题 1.0 文字内容。 固定的内容最简单,能否每一帧都添加不同的内容?能否添加程序自动计算出来的一些信息? 2.0 文字位置。固定位置也最简单,能否每一帧都添加在不同的位置?用一个公式去动态自己确定位置? 3.0 字体,颜色,背景色,逐渐变换的颜色。 一条典型的命令 叠加上每一帧的序号,解码成 raw yuv420p格式

ffmpeg -i native.mp4 -t 10 -vf "drawtext=fontsize=100:x=n*5:y=100:fontcolor=red:box=1:text='%{n}'" -pix_fmt yuv420p 1280x720_yuv420p_test.yuv # -t 10 取前10s ,默认开始时间是0,也可以用参数:-ss 00:00:00 指定时间点 # -vf "" 这里就开始指定滤镜 #fontsize=100 字体大小 还有fontfile='xx' 指定使用的字体文件,我这里wind上执行的使用的系统缺省字体 #x=n*5 y=100 可以直接写固定数值,这里写了个表达式,n*5 n指的是帧序号,所以x坐标是在变化的。 #fontcolor=red 颜色, freetype字库接口支持的 #box=1 box是指字体背景“盒子”, 默认的话是背景透明的,即box=0 . 现在box=1是绘制背景的,box默认颜色白色,也可以通过 boxcolor 修改 #text='%{n}' 这个就有意思了,原本可以直接通过text='hello world' 设置固定的文字,这里是以%{xx}格式,表示扩展功能,当前用的这个扩展功能会将文字设置为每一帧的序号。 #文字还可以从文件加载,通过设置textfile=test_file 设置文件。

 上面的输出如下,添加的文字信息是每一帧自己的序号 ,从0开始, 坐标因为设置了 x=n*5,也是和帧序号相关。

 

一:查看help信息

 ffmpeg 命令行查看某一个滤镜的参数:#ffmpeg --help filter=drawtext

 这些help信息,都是直接在源码中可以查看到的,在源码vf_drawtext.c 的 AVOption结构体中,上面的输出就是从该结构体中取出的字符串,每一个滤镜都有这么一个选项结构体。

二:文字内容的几种来源

     1.0 固定输入: 选项 -text='hello world'       2.0 从文件导入  -textfile='xxx'       3.0 %{xx} 扩展功能  文字内容从这个扩展函数里面生成            3.1  每一帧的pts 时间戳信息                   text='%{pts}'            3.2  当前系统 时间                     text='%{localtime}'                    text='%{gmtime}'  //gmtime和localtime的区别,就不啰嗦了             3.3 每一帧的序号                    text='%{frame_num}'  或者简写成 text='%{n}'             3.4 添加mete 媒体信息                   text='%{metadata\:width}'       这个功能必须携带一个参数,不给参数会报警,这里给的是width,源数据用的mp4,结果发现根本就么有mete信息.  在源码中://下面printf个人添加的,因为使用mp4文件的时候怎么添加mete都没有,结果发现这里 av_dict_count() 为0, 根本没有添加过meta信息,  这个dict, 词典, 存储着键值对信息。。实验失败,没啥用

static int func_metadata(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { DrawTextContext *s = ctx->priv; AVDictionaryEntry *e = av_dict_get(s->metadata, argv[0], NULL, 0); //下面printf个人添加的,因为使用mp4文件的时候怎么添加mete都没有,结果发现这里 av_dict_count() 为0, 根本没有添加过meta信息, 这个dict, 词典, 存储着键值对信息。 printf("[%s%d]argv[0] :%s metacount:%d \n",__FUNCTION__,__LINE__,argv[0],av_dict_count(s->metadata)); if (e && e->value) av_bprintf(bp, "%s", e->value); else if (argc >= 2) av_bprintf(bp, "%s", argv[1]); return 0; }

       3.5 显示帧类型                text='%{pict_type}'               如下图,drawtext了两次同时加上序号和帧类型。 要注意,这里的帧类型,P帧,I帧,B帧, 指的是解码前 h264数据的类型,如果在命令操作的时候保存的是再编码的数据,再编码出来的数据可就和这里的帧类型无关了,滤镜都是在解码后,重编码前作的对raw数据做的像素级别的操作。 所以用命令行:#ffmpeg -i native.mp4 -t 10 -vf "drawtext=fontsize=100:x=0:y=0:fontcolor=red:box=1:text='%{pict_type}'" -vcodec libx264 -bf 0 test_pict_type.h264 输出的重编码的  test_pict_type.h264 画面显示的 log 帧类型,是指 输入文件native.mp4 的帧类型,重编码后的 test_pict_type.h264 帧类型是不一样的。          3.6 扩展表达式。               { "expr_int_format", 2, 3, 0, func_eval_expr_int_format },              { "eif",       2, 3, 0,   func_eval_expr_int_format },             这个就比较厉害了,ffmpeg命令行的参数都支持 表达式类型,比如条件判断,啥都都行,比较复杂,这里就不在此深究了。 源码中可以看到支持的扩展函数功能: 需要以%{} 格式输入: 源码中相关的函数

static int expand_text(AVFilterContext *ctx, char *text, AVBPrint *bp) { int ret; av_bprint_clear(bp); while (*text) { if (*text == '\\' && text[1]) { av_bprint_chars(bp, text[1], 1); text += 2; } else if (*text == '%') { text++; if ((ret = expand_function(ctx, bp, &text)) < 0) return ret; } else { av_bprint_chars(bp, *text, 1); text++; } } if (!av_bprint_is_complete(bp)) return AVERROR(ENOMEM); return 0; } 三:坐标的控制

可以支持表达式扩展 ffmpeg命令行的参数都支持 表达式类型,比如条件判断,啥都都行,比较复杂,这里就不在此深究了。

四:使能,显示时机的控制。

      enable=xxx        这个参数并不是本滤镜所特有的,是滤镜控制的一个公共的参数,上面 help信息中就有说明: This filter has support for timeline through the 'enable' option. 同样这个参数可以支持表达式形式。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有